import asyncio
#import mhttp
from PyQt5.QtCore import pyqtSignal,QThread
import time
import datetime
from dateutil.relativedelta import relativedelta
import re
import json
import win32api
import win32con
import aiohttp
import platform
import os
import sys

import asmsql
import config




class pyqt_thread(QThread):
    Dic_Signal = pyqtSignal(dict)
    def __init__(self):
        super(pyqt_thread, self).__init__()
        self.daemon = True
        self.loop = asyncio.new_event_loop()
        self.mysql = asmsql.sqlitedb(self.loop)

    def run(self):
        asyncio.run_coroutine_threadsafe(self.mysql.init_table(),self.loop)
        self.loop.run_forever()

    def _stop(self):
        self.loop.call_soon_threadsafe(self.loop.stop)
        self.loop.call_soon_threadsafe(self.loop.close)

    def my_call(self,call,*kavy):
        asyncio.run_coroutine_threadsafe(call(self.Dic_Signal,*kavy),self.loop)

    def mycall(self,*kavy):
        asyncio.run_coroutine_threadsafe(mysql_call(self.Dic_Signal,self.mysql,*kavy),self.loop)



async def mysql_call(sig,mysql,*argv):
    code = argv[-1]
    if code == 101:
        if argv[-2] == 'see':
            ret = await see_myid(mysql,argv[0])
            sig.emit({"code":code, "ret":ret, "mode":"see"})
        elif argv[-2] == 'set':
            ret = await mysql.update_mydata(argv[0],argv[1],"1",argv[2],argv[3],argv[4],argv[5])
        elif argv[-2] == 'add':
            write_time = time.strftime("%Y-%m-%d %H:%M:%S")
            ret = await mysql.insert_mydata(argv[0], argv[1], write_time, '0', argv[2], argv[3], argv[4], argv[6])
            if ret:
                sig.emit({"code":code, "ret":"添加成功", "mode":"add"})
                ret = await mysql.get_insert_id("mydata")
                if argv[-3] == "pyqt":
                    res  = await mysql.search_select_mydata("0",argv[6])
                    addr = [int(time.mktime(datetime.datetime.strptime(v[3],"%Y-%m-%d %H:%M:%S").timetuple())) for v in res]
                    if len(addr) > 1:
                        _id  = res[addr.index(min(addr))][0]
                        res = await mysql.set_mydata('1',_id)
                        if res:
                            sig.emit({"code":103, "ret":str(_id), "mode":"del"})
                sig.emit({"code":103, "ret":(ret,argv[0],argv[1], write_time, '0', argv[2], argv[3], argv[4], argv[6], argv[5]), "mode":"addm"})
            else:
                sig.emit({"code":code, "ret":"添加失败，请检查编码信息库是否存在此商品", "mode":"add"})

    elif code == 102:
        if argv[-2] == 'see':
            pass
        elif argv[-2] == 'add':
            pass
    elif code == 103:
        if argv[-2] == 'update':
            ret = await mysql.update_mydata(argv[0],argv[1],"0",argv[2],argv[3],argv[4],argv[5])
            if ret:
                sig.emit({"code":code, "ret":argv, "mode":"set"})
            else:
                sig.emit({"code":code, "ret":ret, "mode":"set"})
        elif argv[-2] == 'add':
            ret = await mysql.select_mydata(argv[0])
            for i in ret:
                if int(time.mktime(datetime.datetime.strptime(i[2],"%Y-%m-%d").timetuple())) < int(time.mktime(datetime.datetime.now().timetuple())):
                    await mysql.set_mydata('1',i[0])
                else:
                    sig.emit({"code":code, "ret":i, "mode":"add"})
            sig.emit({"code":code, "ret":True, "mode":"stop"})
        elif argv[-2] == 'del':
            ret = await mysql.delete_mydata(argv[0])
            if ret:
                sig.emit({"code":code, "ret":argv[1], "mode":"del"})
        elif argv[-2] == 'set':
            ret = await mysql.set_mydata(argv[2],argv[0])
            if ret:
                sig.emit({"code":code, "ret":argv[1], "mode":"del"})
    elif code == 104:
        if argv[-2] == 'see':
            ret = await mysql.search_select_myid(argv[0])
            if not ret:
                ret = ("",argv[0])
            sig.emit({"code":code, "ret":ret, "mode":"see"})
        elif argv[-2] == 'add':
            ret = await mysql.select_myid()
            for i in ret:
                sig.emit({"code":code, "ret":i, "mode":"add"})
        elif argv[-2] == 'del':
            ret = await mysql.delete_myid(argv[0])
            if ret:
                sig.emit({"code":code, "ret":argv[0], "mode":"del"})
            else:    
                sig.emit({"code":code, "ret":ret, "mode":"del"})
        elif argv[-2] == 'set':
            ret = await mysql.update_myid(argv[0],argv[1],argv[2],argv[3],argv[4])
            sig.emit({"code":code, "ret":ret, "mode":"set"})
    elif code == 105:
        ret = await mysql.insert_myid(argv[0],argv[1],argv[2],argv[3],argv[4],argv[5])
        sig.emit({"code":code, "ret":ret, "mode":"add"})
        sig.emit({"code":104, "ret":[argv[0]], "mode":"add"})
    elif code == 106:
        if argv[-2] == 'add':
            ret = await mysql.select_myjizhang(argv[0],argv[1],argv[2])	
            if not ret:
                ret = await mysql.insert_myjizhang(argv[0],argv[1],argv[2],argv[3])
            else:
                ret = await mysql.update_myjizhang(argv[3],argv[0],argv[1],argv[2])
            if ret:
                sig.emit({"code":code, "ret":(argv[0],argv[1],argv[2],argv[3]), "mode":"add"})
        elif argv[-2] == 'see':
            ret = await mysql.select_myjizhang(argv[0],argv[1],None)
            r = 0
            for i in ret:
                sig.emit({"code":code, "ret":i, "mode":"see"})
                r += i[4]
            sig.emit({"code":code, "ret":str(r), "mode":"set"})
    elif code == 1011:
        if argv[-2] == 'see':
            ret = await mysql.search_select_mydata(argv[0],argv[1])
            if ret:
                for i in ret:
                    sig.emit({"code":code, "ret":i, "mode":"add"})
            else:
                sig.emit({"code":code, "ret":ret, "mode":"close"})
        elif argv[-2] == 'set':
            ret = await mysql.search_select_mydata_id(argv[0])
            sig.emit({"code":code, "ret":ret[0], "mode":"add"})



async def see_myid(mysql,mid):
    try:
        ret = await mysql.search_select_myid(mid)
        if not ret:
            appid="yktexshikvjg8lnq"
            appsecret="YlViYzFob3F2a055VjNMZjQxRHljQT09"
            url = "https://www.mxnzp.com/api/barcode/goods/details?app_id={}&app_secret={}&barcode={}".format(appid,appsecret,mid)
            session  =  aiohttp.ClientSession()
            response =  await session.get(url)
            if response.status == 200:
                html = await response.text()
                res = json.loads(html)
                if res['code'] == 1:
                    await mysql.insert_myid(res['data']['barcode'],res['data']['goodsName'],"","",'null','null')
                    ret = [(res['data']['barcode'],res['data']['goodsName'])]
                else:
                    ret = [("","联网查询未找到此商品")]
            else:
                ret = [("","查询服务器失败，请检查查询网站")]
        return ret
    except:
        config.mylog()
        return [("","未知错误已记录日志")]


async def update_icon(sig):
    sig.emit({"code":101, "ret":"更新ico", "mode":"icon"})
    sig.emit({"code":102, "ret":"更新ico", "mode":"icon"})
    sig.emit({"code":103, "ret":"更新ico", "mode":"icon"})
    sig.emit({"code":104, "ret":"更新ico", "mode":"icon"})
    sig.emit({"code":106, "ret":"更新ico", "mode":"icon"})


async def myupdate(sig,url,mid):
    try:    
        session  =  aiohttp.ClientSession()
        response =  await session.post("http://" + url + "/version?mid={}".format(mid))
        if response.status == 200:
            html = await response.text()
            jsondata = json.loads(html)
            if jsondata['code'] == "1":
                if jsondata['version'] != config.__version__:
                    if '64' in platform.python_compiler():
                        exe = 'win64.exe'
                    elif '32' in platform.python_compiler():
                        exe = 'win32.exe'
                    response = await session.post("http://" + url + "/download/{}/{}".format(mid,exe))
                    if response.status == 200:
                        if response.headers['get-post'] == "false":
                            sig.emit({"code":102, "ret":"更新失败，服务器文件丢失", "mode":"err"})
                            return 
                        size = int(response.headers['Content-Length'])
                        stat = 0
                        t = 0
                        pwd = os.path.join(config.mypath, exe)
                        with open(pwd, "wb") as f:
                            while True:
                                data = await response.content.read(4096)
                                if not data:
                                    break
                                f.write(data)
                                stat += 4096
                                h = round((stat/size)*100)
                                if h != t:
                                    t = h
                                    sig.emit({"code":102, "ret":h, "mode":"update"})
                        old = os.path.join(config.mypath, config.mname)
                        new = os.path.join(config.mypath, "new" + config.mname)
                        os.rename(old, new)
                        win32api.SetFileAttributes(new, win32con.FILE_ATTRIBUTE_HIDDEN)
                        os.rename(pwd, old)
                        os.execl(sys.executable, sys.executable)
                else:
                    sig.emit({"code":102, "ret":"", "mode":"vers"})
    except:
        config.mylog()
    finally:
        sig.emit({"code":102, "ret":"", "mode":"close"})



async def main_init(sig):
    files = os.listdir(config.mypath)
    for v in files:
        mpath = os.path.join(config.mypath, v)
        if os.path.isfile(mpath):
            if win32api.GetFileAttributes(mpath) == win32con.FILE_ATTRIBUTE_HIDDEN:
                os.remove(mpath)



def getmtime(stat_time,stop_time):
    def timere(txt,m):
        for i in txt:
            if ord(i) > 57 or ord(i) < 45:
                return (None, m + "不能填非法字符")
        res = re.findall(r"[\.,\-,/]",txt)
        if not res:
            return (None, m + "没有分隔符")
        if len(set(res)) > 1:
            return (None, m + "分隔符填写不一致")
        if len(res) == 1:
            return (None, m + "格式不对")
        txt = txt.replace(res[0], "-")
        try:
            mday = datetime.datetime.strptime(txt,"%Y-%m-%d")
        except:
            return (None, m + "错误的日期年份")
        if m == "保质期":
            if mday < datetime.datetime.now():
                return (None, "过期食品")
        elif m == "生产日期":
            if mday > datetime.datetime.now():
                return (None, "未生产食品")
        return (txt, None)

    stat_time = stat_time.replace(" ","")
    stop_time = stop_time.replace(" ","")
    if not stop_time:
        return (None, "保质期不能为空")
    if stat_time:
        ret = timere(stat_time, "生产日期")
    else:
        ret = (time.strftime("%Y-%m-%d"), None)
    if not ret[0]:
        return ret
    if len(stop_time) > 4:
        res = timere(stop_time, "保质期")
        if not res[0]:
            return res
    else:
        try:
            if '.' in stop_time:
                day = stop_time.split(".")[1]
                mday = datetime.datetime.strptime(ret[0], "%Y-%m-%d") + datetime.timedelta(days=int(day))
            else:
                formt   = int(stop_time)//12
                tomonth = int(stop_time) - (int(stop_time)//12)*12
                mday = datetime.datetime.strptime(ret[0], "%Y-%m-%d") + relativedelta(years=formt,months=tomonth)
        except:
            return (None, "错误的保质期格式")        
        res = (str(mday)[:10], None)
    return (ret[0],res[0])



def addfile2autorun(path,run):
    runpath = "Software\Microsoft\Windows\CurrentVersion\Run"
    hKey = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER, runpath, 0, win32con.KEY_ALL_ACCESS)
    if run:
        win32api.RegSetValueEx(hKey, "mainappexe",0, win32con.REG_SZ, path)
    else:
        win32api.RegDeleteValue(hKey, "mainappexe")
    win32api.RegCloseKey(hKey)
